package org.wesc.boot.webapi.api.system;

import com.baomidou.mybatisplus.core.toolkit.StringPool;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.wesc.boot.common.annotation.ApiEndpoint;
import org.wesc.boot.common.api.R;
import org.wesc.boot.dao.domain.QueryRequest;
import org.wesc.boot.dao.entity.Notice;
import org.wesc.boot.dao.entity.User;
import org.wesc.boot.secure.jwt.JwtUtil;
import org.wesc.boot.service.system.notice.NoticeAdvanceService;
import org.wesc.boot.service.system.notice.UserMessageAdvanceService;
import org.wesc.boot.service.system.user.UserAdvanceService;
import org.wesc.boot.webapi.base.BaseApi;

import javax.validation.Valid;
import javax.validation.constraints.NotBlank;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 系统通告API
 * @author Wesley
 * @date 2021/3/24
 */
@Api(tags={"系统通告"})
@Slf4j
@Validated
@RestController
@RequestMapping("/api/notice")
public class NoticeApi extends BaseApi {

    private static final int UNREAD_LIMIT = 3;

    private final UserAdvanceService userAdvanceService;

    private final NoticeAdvanceService noticeAdvanceService;

    private final UserMessageAdvanceService userMessageAdvanceService;

    @Autowired
    public NoticeApi(UserAdvanceService userAdvanceService,
                     NoticeAdvanceService noticeAdvanceService,
                     UserMessageAdvanceService userMessageAdvanceService) {
        this.userAdvanceService = userAdvanceService;
        this.noticeAdvanceService = noticeAdvanceService;
        this.userMessageAdvanceService = userMessageAdvanceService;
    }

    @ApiOperation(value = "获取通告列表")
    @GetMapping("/list")
    @RequiresPermissions("notice:view")
    public R<Map<String, Object>> list(QueryRequest request, Notice notice) {
        return R.data(getDataTable(this.noticeAdvanceService.pageQueryList(request, notice)));
    }

    @ApiOperation(value = "新增通告")
    @PostMapping(value = "/add")
    @RequiresPermissions("notice:add")
    @ApiEndpoint(operation = "新增通告", exception = "新增通告失败")
    public R<Notice> add(@Valid Notice notice) {
        notice = this.noticeAdvanceService.create(notice, JwtUtil.getCurrentUserName());
        return R.data(notice);
    }

    @ApiOperation(value = "删除通告")
    @DeleteMapping("/{ids}")
    @RequiresPermissions("notice:delete")
    @ApiEndpoint(operation = "删除通告", exception = "删除通告失败")
    public R<String> delete(@NotBlank(message = "{required}") @PathVariable String ids) {
        try {
            String[] noticeIds = ids.split(StringPool.COMMA);
            this.noticeAdvanceService.batchDelete(noticeIds, JwtUtil.getCurrentUserName());
            return R.success();
        } catch (Exception e) {
            String message = "删除通告失败";
            log.error(message, e);
            return R.fail(message);
        }
    }

    @ApiOperation(value = "编辑通告")
    @PutMapping(value = "/update")
    @RequiresPermissions("notice:update")
    @ApiEndpoint(operation = "编辑通告", exception = "编辑通告失败")
    public R<Notice> update(@Valid Notice notice) {
        try {
            this.noticeAdvanceService.update(notice, JwtUtil.getCurrentUserName());
            return R.success();
        } catch (Exception e) {
            String message = "编辑通告失败";
            log.error(message, e);
            return R.fail(message);
        }
    }

    @ApiOperation(value = "发布通告")
    @GetMapping(value = "/publish")
    @RequiresPermissions("notice:publish")
    @ApiEndpoint(operation = "发布通告", exception = "发布通告失败")
    public R<Notice> doPublish(@RequestParam(name="noticeId") String noticeId) {
        String currentUserName = JwtUtil.getCurrentUserName();
        Notice notice = this.noticeAdvanceService.publish(currentUserName, noticeId);
        if (null == notice) {
            return R.fail("未找到对应实体");
        } else {
            return R.data(notice, "通告发布成功");
        }
    }


    @ApiOperation(value = "撤销通告")
    @GetMapping(value = "/revoke")
    @RequiresPermissions("notice:revoke")
    @ApiEndpoint(operation = "撤销通告", exception = "撤销通告失败")
    public R<Notice> doRevoke(@RequestParam(name = "noticeId") String noticeId) {
        Notice notice = this.noticeAdvanceService.revoke(noticeId);
        if(null == notice) {
            return R.fail("未找到对应实体");
        } else {
            return R.data(notice, "通告撤销成功");
        }
    }

    @ApiOperation(value = "同步通告")
    @GetMapping(value = "/sync")
    public R<Notice> doSync(@RequestParam(name = "noticeId", required = false) String noticeId) {
        String currentUserName = JwtUtil.getCurrentUserName();
        User currentUser = this.userAdvanceService.findByUserName(currentUserName);
        String userId = String.valueOf(currentUser.getUserId());
        if(StringUtils.isBlank(noticeId)){
            this.noticeAdvanceService.syncAll(userId);
            return R.success("所有消息已同步");
        }
        Notice notice = this.noticeAdvanceService.sync(userId, noticeId);
        if (null == notice) {
            return R.fail("未找到对应实体");
        } else {
            return R.data(notice, "此消息已同步");
        }
    }

    @ApiOperation(value = "查询用户消息")
    @GetMapping(value = "/listByUser")
    public R<Map<String,Object>> listByUser() {
        String currentUserName = JwtUtil.getCurrentUserName();
        User currentUser = this.userAdvanceService.findByUserName(currentUserName);
        String userId = String.valueOf(currentUser.getUserId());

        // 补充用户数据
        this.userMessageAdvanceService.fillUserMessage(currentUser);

        // 查询用户未读的系统消息
        List<Notice> noticeList = this.userMessageAdvanceService.queryUnreadListByUserId(userId);
        Map<String,Object> msgMap = new HashMap<>(4);
        msgMap.put("msgTotal", noticeList.size());
        if (noticeList.size() > UNREAD_LIMIT) {
            msgMap.put("msgList", noticeList.subList(0, UNREAD_LIMIT));
        } else {
            msgMap.put("msgList", noticeList);
        }

        return R.data(msgMap);
    }

}
